(define-module (list-utils)
  #:export (list-prefix?
            multirember*-with-equal-proc
            multirember-with-equal-proc
            multirember-equal
            multirember*-equal))


(define list-prefix?
  (λ (lst lst-prefix)
    (cond
     [(null? lst-prefix) #t]
     [(null? lst) #f]
     [else
      (cond
       [(equal? (car lst) (car lst-prefix))
        (list-prefix? (cdr lst) (cdr lst-prefix))]
       [else #f])])))


;; scheme@(guile-user)> (list-prefix? '(a b c) '(a b))
;; $11 = #t
;; scheme@(guile-user)> (list-prefix? '(a b c) '(a b c))
;; $12 = #t
;; scheme@(guile-user)> (list-prefix? '(a b c) '(a b c d))
;; $13 = #f
;; scheme@(guile-user)> (list-prefix? '(a b c) '(a))
;; $14 = #t
;; scheme@(guile-user)> (list-prefix? '(a b c) '(b))
;; $15 = #f
;; scheme@(guile-user)> (list-prefix? '(a b c) '())
;; $16 = #t
;; scheme@(guile-user)> (list-prefix? '(a b c) '())


(define multirember*-with-equal-proc
  (λ (equal-proc)
    (λ (lst unwanted)
      (let loop ([remaining-list lst])
        (cond
         [(null? remaining-list)
          '()]
         ;; case for finding the unwanted element in the list
         [(equal-proc (car remaining-list) unwanted)
          (loop (cdr remaining-list))]
         ;; case for handling nested lists
         [(pair? (car remaining-list))
          (cons (loop (car remaining-list))
                (loop (cdr remaining-list)))]
         [else
          (cons (car remaining-list)
                (loop (cdr remaining-list)))])))))


(define multirember-with-equal-proc
  (λ (equal-proc)
    (λ (lst unwanted)
      (let loop ([remaining-list lst])
        (cond
         [(null? remaining-list)
          '()]
         [(equal-proc (car remaining-list) unwanted)
          (loop (cdr remaining-list))]
         [else
          (cons (car remaining-list)
                (loop (cdr remaining-list)))])))))


(define multirember-equal
  (multirember-with-equal-proc equal?))


(define multirember*-equal
  (multirember*-with-equal-proc equal?))


;; (define list-left-trim-with-equality-proc
;;   (λ (equality-proc)
;;     (λ (lst unwanted)
;;       (let loop ([remaining-list lst])
;;         (cond
;;          [(null? remaining-list) '()]
;;          ;; case for finding the unwanted element in the list
;;          [(equality-proc (car remaining-list) unwanted)
;;           (loop (cdr remaining-list))]
;;          ;; case for handling nested lists
;;          [(pair? (car remaining-list))
;;           remaining-list]
;;          [else
;;           ;; prefix of unwanted elements ended
;;           remaining-list])))))


;; (define list-left-trim-empty-strings
;;   (λ (lst-of-str)
;;     ((list-left-trim-with-equality-proc string=?) lst-of-str "")))
